﻿using System.Collections;

namespace Aliphant.Common.Tools
{
    public class CoroutineManager
    {
        private static CoroutineManager? _instance = null;
        public static CoroutineManager Instance
        {
            get => _instance ?? (_instance = new CoroutineManager());
        }

        private LinkedList<Coroutine> _startLink = new LinkedList<Coroutine>();

        private LinkedList<Coroutine> _stopLink = new LinkedList<Coroutine>();

        public Coroutine StartCoroutine(IEnumerator enumerator)
        {
            var coroutine = new Coroutine(enumerator);
            _startLink.AddLast(coroutine);
            return coroutine;
        }

        public void StopCoroutine(Coroutine coroutine)
        {
            Console.WriteLine("协程管理器——停止协程");
            _stopLink.AddLast(coroutine);
        }

        public void StopAllCoroutine()
        {
            var node = _startLink.First;
            while (node != null)
            {
                if (!_stopLink.Contains(node.Value))
                {
                    _stopLink.AddLast((Coroutine)node.Value);
                }
                node = node.Next;
            }
        }

        public void Run()
        {
            var node = _startLink.First;
            while (node != null)
            {
                Coroutine coroutine = node.Value;
                bool ret = false;
                if (coroutine != null)
                {
                    // 该协程是否处于停止状态
                    bool toStop = _stopLink.Contains(coroutine);
                    if (!toStop)
                    {
                        // 更新该协程执行，一旦协程对象返回false，即意味着遍历到末尾了，改协程要退出
                        ret = coroutine.MoveNext();
                    }
                }
                if (!ret)
                {
                    // 当协程遍历到末尾，停止该协程
                    coroutine?.Stop();
                    _startLink.Remove(node);
                    //Console.WriteLine("[CoroutineManager] remove coroutine");
                }
                node = node.Next;
            }
        }
    }
}
